package com.wanger.swa.config;

import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;

import java.util.Collections;

/**
 * @Author: wanger
 * @Date: 2024/9/16 3:08
 * @Description: swagger配置
 */
@Configuration
@EnableSwagger2WebMvc
@RequiredArgsConstructor
@EnableConfigurationProperties({
        SwaggerConfig.SwaggerProperty.class,
        SwaggerConfig.ApiKeyProperty.class,
        SwaggerConfig.ContactProperty.class,
})
public class SwaggerConfig {
    /**
     * 基本属性配置
     */
    private final SwaggerProperty swaggerProperty;

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())

                .build()
                .host(swaggerProperty.host)
                .enable(swaggerProperty.enabled)
                .securitySchemes(Collections.singletonList(apiKey()))
                .securityContexts(Collections.singletonList(securityContext()));
    }

    private ApiKey apiKey() {
        ApiKeyProperty apiKey = swaggerProperty.getApiKey();
        return new ApiKey(apiKey.name, apiKey.keyname, apiKey.passAs);
    }

    private SecurityContext securityContext() {
        ApiKeyProperty apiKey = swaggerProperty.getApiKey();
        return SecurityContext.builder()
                .securityReferences(Collections.singletonList(new SecurityReference(apiKey.keyname, new AuthorizationScope[0])))
                .build();
    }

    private ApiInfo apiInfo() {
        ContactProperty contact = swaggerProperty.getContact();
        return new ApiInfoBuilder()
                .title(swaggerProperty.title)
                .description(swaggerProperty.description)
                .contact(new Contact(contact.name, contact.url, contact.email))
                .version(swaggerProperty.version)
                .build();
    }

    /**
     * Swagger 配置属性类
     */
    @Data
    @ConfigurationProperties(prefix = "swagger")
    public static class SwaggerProperty {

        /**
         * 是否启用 Swagger
         */
        private Boolean enabled = Boolean.FALSE;

        /**
         * API 标题
         */
        private String title;

        /**
         * API 主机名
         */
        private String host;

        /**
         * API 描述
         */
        private String description;

        /**
         * 服务条款 URL
         */
        private String termsOfServiceUrl;

        /**
         * 许可证名称
         */
        private String license;

        /**
         * 许可证 URL
         */
        private String licenseUrl;

        /**
         * API 版本
         */
        private String version;

        /**
         * 联系人信息
         */
        private ContactProperty contact;

        /**
         * API 密钥配置
         */
        private ApiKeyProperty apiKey;
    }

    /**
     * API 密钥配置属性类
     */
    @Data
    @ConfigurationProperties(prefix = "swagger.api-key")
    static class ApiKeyProperty {
        /**
         * 密钥名称
         */
        private String name;

        /**
         * 密钥类型（例如：apiKey、http等）
         */
        private String type;

        /**
         * 密钥描述
         */
        private String description;

        /**
         * 密钥名称在请求中的名称
         */
        private String keyname;

        /**
         * 密钥在请求中的传递方式（例如：header、query等）
         */
        private String passAs;
    }

    /**
     * 联系人信息属性类
     */
    @Data
    @ConfigurationProperties(prefix = "swagger.contact")
    static class ContactProperty {
        /**
         * 联系人姓名
         */
        private String name;

        /**
         * 联系人 URL
         */
        private String url = "暂无";

        /**
         * 联系人邮箱
         */
        private String email;
    }

}

